iT邦幫忙

2024 iThome 鐵人賽

DAY 25
0
Python

從概念到應用:Python實戰開發學習之旅系列 第 25

[Day24] Python專案 - 網頁開發 - (3) 前端的至尊React與Python之間的交流

  • 分享至 

  • xImage
  •  

目標

https://ithelp.ithome.com.tw/upload/images/20241009/201210525QY8bVTGAW.png

前言

昨天再經過python後端API的CRUD開發之後
高速的服務提供者Fast API

今天會介紹React的基本使用方式

不過我會講道說為什麼會使用這些框架,跟傳統三劍客(HTML、JS、CSS)有什麼差別
以及React(前端)工程師在開發時的會思考的東西

今日學習重點

今天會學到
1.前端工程師該思考的事情
2.React的建置跟基本語法
3.前後端的交互


1. 前端工程師該思考的事情

1.1 十大提升前端工程師的技能

# 注意事項 說明
1 UI/UX 設計 確保應用程式具有流暢、直觀的使用體驗(UX)和美觀、一致的介面設計(UI),以提升用戶滿意度。
2 狀態儲存與管理 使用狀態管理工具(如Redux、Vuex、MobX)管理應用的全局狀態,確保資料流動一致,方便擴展和調試。
3 HTTP 請求與 API 交互 通過工具(如fetch或Axios)發送HTTP請求,處理數據的異步操作,並考慮API請求的安全性與錯誤處理。
4 組件化開發 將應用拆分為小型可重用組件,管理組件之間的資料流動,提高代碼結構的可維護性和可讀性。
5 響應式設計與跨裝置兼容性 透過CSS媒體查詢確保應用適應不同螢幕尺寸,並確保應用在主流瀏覽器上的表現一致。
6 性能優化 優化資源加載、代碼分割、圖片Lazy Loading等技術,確保應用加載迅速並提升用戶體驗。
7 無障礙設計(A11y) 確保網站對於有視覺、聽覺或其他障礙的用戶可訪問,遵循WCAG標準,提供鍵盤導航等無障礙功能。
8 安全性 防範XSS、CSRF等攻擊,進行輸入驗證,確保應用數據的安全性,並使用身份驗證來保護API請求。
9 國際化(i18n)和本地化(l10n) 支持多語言和多地區的需求,提供日期、貨幣等本地格式的動態切換功能,以適應不同市場。
10 動效與過渡效果 使用CSS或JavaScript的動效提升用戶體驗,但要平衡性能,確保應用運行流暢且不卡頓。

這幾個都是前端工程師的必學技能
不過就新手而言我建議先朝HTTP 請求與 API 交互組件化開發響應式設計與跨裝置兼容性
三個方向去學習

為什麼呢~!?
這個也是我個人的主觀見解

今天在開發一個網站應用程式(Web Application)
最重要的是:
HTTP請求與API交互(儲存使用者的資料=>前端傳到後端資料庫存放)
組件化開發 透過現代前端框架有效的拆分組件(類似python modular programming的概念)
響應式設計 各種裝置平台瀏覽都有最適應的畫面

1.2 HTTP請求與API交互

https://ithelp.ithome.com.tw/upload/images/20241009/20121052X92w22KHRN.png

這個圖在前面也有呈現過類似的
但今天以前端工程師角度來說會思考更多點
大家可以參考下面的重點,還有我個人的心得補充

1. 異步處理(早餐店老闆娘)

  • 異步操作:使用async/awaitPromise來處理HTTP請求,確保不會阻塞前端其他操作。
  • 併發請求處理:有效管理多個請求,避免競爭條件(Race Condition)和資源衝突。

可以想像成今天你在早餐店點了奶茶跟烤巧克力土司

  1. 老闆娘會先丟兩片吐司進去土司機烤
  2. 在做奶茶奶茶完成
  3. 跟你收錢
  4. 最後把烤好吐司拿起來抹醬
  5. 最後包裝給你

https://ithelp.ithome.com.tw/upload/images/20241009/20121052vuDMqWzKtN.png
有沒有發現重點!?

今天所有動作都不會一樣一樣完成(點餐->收錢->烤土司->做奶茶->打包)
而是會拆解處理的動作,我最喜歡用早餐店老闆娘解釋這個情境XDD

2. 錯誤處理

  • 網路錯誤:有效處理伺服器無法響應或網路問題的情況,顯示適當的錯誤訊息給使用者。
  • HTTP狀態碼:根據不同的HTTP狀態碼(如400、404、500等)處理不同的錯誤情況,並確保響應正確的UI更新。
  • 重試邏輯:對於請求失敗時,考慮實現自動重試機制。

這個就很常看到了,今天如果是網路問題通常會直接跳伺服器引擎的錯誤看不到畫面(nginx error)
但如果是API請求失敗,比如說你案送出按鈕,後端回傳失敗,這時候前端工程師接到錯誤就要呈現錯誤畫面。

3. 超時處理

  • 請求超時:設置請求的最大等待時間,避免請求卡住。
  • Loading狀態:在請求期間顯示loading動畫,讓用戶了解應用正在處理請求。

4. 安全性

  • 身份驗證與授權:確保請求中包含適當的身份驗證資訊,如Token(JWT)。
  • 防範XSS與CSRF:防止跨站腳本攻擊和跨站請求偽造。
  • HTTPS加密:確保所有請求通過HTTPS進行,保護數據傳輸。

5. 數據解析與格式

  • JSON格式處理:正確解析和處理API返回的JSON數據。
  • 錯誤數據結構處理:做好防禦性編碼,防止應用崩潰。

6. 性能優化

  • 請求緩存:對不經常變動的數據考慮使用緩存,減少重複請求。
  • Debouncing/Throttling:限制請求的頻率,避免不必要的多次請求。
  • Lazy Loading:僅在需要時才發送請求。

7. 跨域請求處理(CORS)

  • 跨域資源共享(CORS):確保前端能夠正確處理跨域請求。

8. 請求取消

  • 請求中止(Abort):使用AbortController來取消不再需要的請求。

9. 請求合併與批量處理

  • 合併多個請求:在可能的情況下合併多個小請求為一個請求。
  • 批量處理:一次請求獲取多筆數據,減少網絡開銷。

10. 版本控制與回退機制

  • API版本控制:處理不同版本的API變更。
  • 回退機制:設計回退機制,以保證應用不會因單個API失敗而崩潰。

11. 國際化與本地化

  • 處理不同語言和格式:根據用戶的設置正確處理多語言和不同格式的數據。

1.3 組件化開發

我們可以創建一個範例
功能是一個counter畫面以及按鈕可以控制加減的網頁
直接讓大家看到下面的程式來比較

html開發counter功能(畫面、控制按鈕) 左邊
vs
React 組件化開發功能(Counter父組件、Counter Display、 Counter Control) 右邊

https://ithelp.ithome.com.tw/upload/images/20241009/201210524SnqjDEHXv.png

HTML + JavaScript(傳統開發)

優點

  1. 簡單易懂:對於小型項目或簡單的功能,使用原生HTML和JavaScript可以直接進行開發,易於理解。
  2. 快速啟動:無需設置複雜的開發環境,可以快速開始編寫代碼。
  3. 無依賴性:不需要安裝額外的庫或框架,減少了依賴性問題。

缺點

  1. 維護困難:隨著代碼量的增長,難以維護和擴展,因為所有邏輯和視圖都混合在一起。
  2. 重複代碼:可能會在多個位置重複相同的代碼,導致代碼膨脹。
  3. 狀態管理困難:狀態管理變得複雜,尤其是在需要多個UI組件相互交互的情況下。
  4. 缺乏組件化:難以構建可重用的組件,影響開發效率。

使用場景

  • 小型靜態網站或簡單的單頁應用。
  • 不需要高互動性的頁面。
  • 短期項目或一次性的功能開發。

React(組件化開發)

優點

  1. 組件化架構:將UI拆分為獨立的可重用組件,提升可維護性和可重用性。
  2. 高效的狀態管理:使用Hooks(如useStateuseEffect)管理狀態和副作用,使狀態變化更為簡單和直觀。
  3. 虛擬DOM:React的虛擬DOM技術能有效提高性能,減少不必要的DOM操作。
  4. 生態系統:擁有豐富的生態系統和庫,可以快速集成各種功能(如路由、狀態管理等)。
  5. 社群支持:擁有大量文檔和社群資源,便於學習和解決問題。

缺點

  1. 學習曲線:對於初學者來說,理解JSX、組件生命週期和Hooks等概念可能會有一定的挑戰。
  2. 配置複雜性:需要設置開發環境(如Webpack、Babel等),對於小型項目來說可能顯得繁瑣。
  3. 性能問題:在不正確使用的情況下,可能會導致性能瓶頸,例如不必要的重新渲染。

使用場景

  • 中大型應用,尤其是需要高互動性和複雜狀態管理的情況。
  • 須要可重用組件的場景,例如電子商務平台、社交媒體網站等。
  • 項目需要長期維護和擴展。

總結

  • HTML + JavaScript:適合簡單、短期的項目,對於小型應用而言可以快速實現,開發門檻較低,但隨著項目複雜度的增加,維護困難。
  • React:提供了一個組件化的解決方案,適合中大型應用開發,尤其是需要互動和狀態管理的場景,但初學者可能需要一些時間來學習。

1.4 RWD 響應式網頁開發

這邊不會講到艱澀的RWD開發模式
不過可以讓大家了解這個模式的應用會有什麼差別

IT邦的畫面

桌面版本
https://ithelp.ithome.com.tw/upload/images/20241009/20121052SuYijLraCF.png

手機版本

https://ithelp.ithome.com.tw/upload/images/20241009/20121052tGNnYjZdMX.png

類別 優點 缺點 應用場景
RWD - 提高使用者體驗,適應各種裝置 - 開發時間可能較長,需考慮多種設備的適配 - 中大型網站,需支援各種裝置的網站
- 透過單一代碼庫簡化維護 - 需要更複雜的CSS和JavaScript - 需要在行動裝置和桌面裝置上保持一致性的網站
- 有助於SEO,Google更喜歡響應式設計 - 可能出現性能問題,特別是在低效的設備上 - 電子商務平台,提升用戶購物體驗
- 提升加載速度,避免重複內容 - 測試和調試工作量增加 - 需要高互動性的網站,例如社交媒體平台

2.React的建置跟基本語法

2.1 必要安裝

前端框架要運行的環境一定要安裝nodejs
https://nodejs.org/zh-tw

使用vite建立 react

https://vite.dev/guide/

可以使用這種交互命令的方式自己選擇(react(有一堆框架可以點,用上下選react按enter) -> javascript)

npm create vite@latest

或是直接用template-react來操作(reactapp 是我命名的名字)

$ npm create vite@latest reactapp --template react

https://ithelp.ithome.com.tw/upload/images/20241009/20121052ZWMVXBjJlQ.png

進去裡面可以按照步驟

npm install 
npm run dev

接者輸入http://localhost:5173/
應該就可以看到我們成功運行react app搂~
https://ithelp.ithome.com.tw/upload/images/20241009/20121052aBAdgqV2iS.png

恭喜學會前端了(X)
等等~這只是開始呢~地獄門才剛進去
/images/emoticon/emoticon15.gif

2.2 React 檔案結構

** Vite + React 基本檔案目錄結構與說明**

.
├── public/
│   └── index.html       # 入口 HTML 文件
├── src/
│   ├── assets/          # 靜態資源 (圖片、樣式等)
│   ├── components/      # React 組件
│   ├── App.jsx          # 主 React 組件,應用入口
│   ├── main.jsx         # 應用啟動文件,掛載 React 進入點
│   └── index.css        # 全局樣式
├── .gitignore           # 忽略的文件規則(Git)
├── package.json         # 項目配置文件,定義依賴和腳本
├── vite.config.js       # Vite 配置文件
├── README.md            # 項目簡介與說明
└── node_modules/        # 依賴庫目錄(自動生成)
  • public/index.html: 應用程序的入口點,Vite 將自動將 JavaScript 應用程式插入此處。
  • src/assets/: 放置靜態資源,如圖片、字體和樣式文件等。
  • src/components/: 用於存放 React 的各個組件,這是項目組件化的基礎。
  • src/App.jsx: 主 React 組件,通常用於定義應用的整體結構與路由等。
  • src/main.jsx: React 進入點,將 App 組件掛載到 DOM 中,啟動應用。
  • src/index.css: 全局樣式文件,定義應用的基本樣式規則。
  • .gitignore: 定義哪些文件和目錄不應提交到版本控制系統(如node_modules/)。
  • package.json: 項目的配置文件,包含依賴、腳本、項目名稱等基本信息。(類似所需套件的列表,使用npm install可以把列表的套件全部窗起來,這份丟給夥伴使用可以快速安裝相同的套件庫)
  • vite.config.js: Vite 的配置文件,用於定義構建配置、插件等。
  • README.md: 項目的說明文件,描述項目的功能、使用方法等。
  • node_modules/: 存放項目依賴的第三方庫,通過 npm 或 yarn 自動生成。(剛開始的npm install安裝完的套件庫會放這邊,通常nodejs開發的環境都會裝到當前資料前而非全域喔!!)

這邊在安裝完後主要會使用到的只有app.jsx跟component/底下的組件
通常新手我會建議把assets,css刪掉避免過多檔案混淆學習

https://ithelp.ithome.com.tw/upload/images/20241009/20121052Q2RrKnOFyx.png

tips React的HTML
大家看到這張圖有沒有覺得似曾相似
沒錯我們曾經在爬蟲實的時候有學習過
當初為什麼抓不到html tag /images/emoticon/emoticon04.gif

其實就是因為這個原因
在前端框架中通常html進入點都只有<div id = root><div>的 root html tag進入
剩下的畫面都是透過Javascript動態產生

那組件我們可以很簡單理解就是畫面的功能
我們可以透過jsx的語法來實現

jsx的基本介紹

JSX 是 JavaScript 的一種語法擴展,允許你在 JavaScript 代碼中寫類似 HTML 的語法,並用來描述 React 元素的樹狀結構。JSX 讓編寫 React 組件變得更加直觀和便捷。

順序就是JSX(翻譯過後) -> Javascript ->HTML

  1. JSX 元素:類似 HTML 的語法,但 JSX 必須包含在單個父元素中。
    2.表達式插值:可以使用 {} 在 JSX 中插入 JavaScript 表達式。 (大括號可以塞javascript變數)
  2. 類屬性名稱:在 JSX 中,使用 className 而不是 class,因為 class 是 JavaScript 的保留字。
    4.自閉合標籤:像 <img /> 或 <input /> 等無子元素的標籤需要自閉合。

我是JSX

// 一個簡單的 React 組件使用 JSX
import React from 'react';

function Greeting(props) {
  return (
    <div>
      <h1>Hello, {props.name}!</h1>
      <p>Welcome to the world of JSX and React.</p>
    </div>
  );
}

export default Greeting;

我是Javascript

React.createElement(
  'div',
  null,
  React.createElement('h1', null, 'Hello, ', props.name, '!'),
  React.createElement('p', null, 'Welcome to the world of JSX and React.')
);

我是html

<div>
  <h1>Hello, John!</h1>
  <p>Welcome to the world of JSX and React.</p>
</div>

3.前後端的交互

經過前面的簡易介紹我們今天就把程式碼串接起來吧
雖然我不會詳細的講解javascript跟jsx
但是我會把必要的邏輯講解後再大家看

不過相信對學到這邊python的你
javascript不會太難的XDD

我們把昨天的Fast API運行起來吧~!!

接者我們要安裝axios

npm install axios

3.1 Axios 簡介

Axios 是一個基於 Promise 的 HTTP 客戶端,用於瀏覽器和 Node.js 中發送 HTTP 請求。它可以用來處理與伺服器之間的數據交換,例如 GET、POST、PUT、DELETE 等請求。它比傳統的 XMLHttpRequest 更加簡潔,並且可以自動處理 JSON 數據。

簡單說就是讓我們跟後端api界街的工具庫

** Axios 的特點 **

  • Promise API:使用 Promise,使得處理異步請求更加簡單。
  • 支援瀏覽器和 Node.js:可以在不同的環境下使用,如 Web 瀏覽器和後端的 Node.js。
  • 自動轉換 JSON:Axios 會自動將 JavaScript 對象轉換為 JSON,並自動解析伺服器回應的 JSON 數據。
  • 攔截器:可以攔截請求和回應,讓你可以在發送請求或處理回應時執行額外的操作。
  • 錯誤處理:能夠捕獲錯誤並進行處理,例如網絡錯誤、伺服器錯誤等。
  • 取消請求:可以通過 CancelToken 來取消正在進行的請求。

3.2 React Get 後端資料

今天很簡單我們就是目標要把Postman 測試的到的Get API 資料傳回來

首先我們先打開前端的資料夾App.jsx
把這串react程式碼貼過去
在npm run dev運行程式碼

如果網站有噴錯誤(應該說肯定)
我們要先把css跟svg在main.jsx使用到的css砍掉

// src/App.jsx
import React, { useState, useEffect } from 'react';
import axios from 'axios';

function App() {
  const [customers, setCustomers] = useState([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    // 使用 axios 發送 GET 請求
    axios.get('http://127.0.0.1:8000/customers/')
      .then(response => {
        setCustomers(response.data);  // 將 API 返回的數據設置到 state 中
        setLoading(false);             // 請求完成後設置 loading 為 false
      })
      .catch(err => {
        setError(err);                 // 設置錯誤狀態
        setLoading(false);
      });
  }, []);

  if (loading) {
    return <div>Loading...</div>;
  }

  if (error) {
    return <div>Error: {error.message}</div>;
  }

  return (
    <div>
      <h1>Customers</h1>
      <ul>
        {customers.map(customer => (
          <li key={customer.id}>{customer.name}</li>
        ))}
      </ul>
    </div>
  );
}

export default App;

我們透過這串React前端期望可以先把昨天後端Get回來呈現到畫面上
但實際上會看到這個
https://ithelp.ithome.com.tw/upload/images/20241009/20121052TjgvQIapKU.png

CORS(Cross-Origin Resource Sharing)

是一種安全機制,允許網頁從不同的域名請求資源。這是為了克服瀏覽器的同源政策(Same-Origin Policy),該政策限制了網頁只能訪問與其來源相同的資源。CORS 通過 HTTP 標頭來告訴瀏覽器哪些外部來源可以訪問特定的資源。
CORS 的主要功能

  • 允許跨域請求:CORS 使得前端應用可以安全地從不同域名或端口的伺服器請求資源。
  • 預檢請求:對於某些複雜的請求,瀏覽器會先發送一個 OPTIONS 請求來確認伺服器是否允許這種請求。
  • 安全性:CORS 允許伺服器精確控制哪些來源可以訪問其資源,從而增強安全性。
  • 同一 IP 不同端口的情況
    根據 CORS 的定義,同一 IP 地址但不同端口的請求也被視為跨域請求。例如,http://example.com:80 http://example.com:3000 被認為是不同的來源。這也是為什麼都是在本機執行但不能通,因為前端(port 5173) 跟後端port 8000不一樣,瀏覽器判定不同源

後端修改 在昨天的server.py新增cors套件

#import新的東西進來
from fastapi.middleware.cors import CORSMiddleware

#這行不變
app = FastAPI() 

#這段落新增
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],  # 或者指定你的前端網址,例如 ["http://localhost:3000"]
    allow_credentials=True,
    allow_methods=["*"],  # 允許所有 HTTP 方法,例如 GET、POST、PUT、DELETE 等
    allow_headers=["*"],   # 允許所有請求標頭
)

厲害吧只要有安裝fast api就會有幫忙處理的middleware喔
重新運行server.py後
我們再重新看前端畫面就會有瞜~!!

https://ithelp.ithome.com.tw/upload/images/20241009/20121052LAfnvIJP8b.png

3.3 拆解 React程式碼架構

引入庫

import React, { useState, useEffect } from 'react';
import axios from 'axios';

  • React: 引入 React 庫,以便使用 React 的功能。
  • useState 和 useEffect: 這兩個是 React 的 Hook,用於管理狀態和處理副作用(如 API 請求)。
  • axios: 引入 axios 庫,用於發送 HTTP 請求。

定義組件

react 組件都是用function來定義

function App() {
}

定義狀態

  const [customers, setCustomers] = useState([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

Rreact 可以透過狀態改變,自動重新渲染組件 => 就是有值改變會自動重新刷新不用重整,強吧!!

  • customers: 用來存儲從 API 獲取的客戶數據,初始值為空陣列。
  • loading: 用來指示數據加載的狀態,初始值為 true,表示正在加載。
  • error: 用來存儲可能發生的錯誤,初始值為 null,表示沒有錯誤。

使用 useEffect 發送 API 請求

  useEffect(() => {
    axios.get('http://127.0.0.1:8000/customers/')
      .then(response => {
        setCustomers(response.data);  // 將 API 返回的數據設置到 state 中
        setLoading(false);             // 請求完成後設置 loading 為 false
      })
      .catch(err => {
        setError(err);                 // 設置錯誤狀態
        setLoading(false);
      });
  }, []);

useEffect: 在組件首次渲染時執行這段代碼,發送 GET 請求到後端 API (http://127.0.0.1:8000/customers/)。

axios.get: 發送請求,然後根據結果執行以下操作:
.then: 請求成功後,將返回的數據(response.data)設置到 customers 狀態中,並將 loading 設置為 false。
.catch: 如果請求失敗,將錯誤信息設置到 error 狀態中,並將 loading 設置為 false。

顯示顧客的資料

  return (
    <div>
      <h1>Customers</h1>
      <ul>
        {customers.map(customer => (
          <li key={customer.id}>{customer.name}</li>
        ))}
      </ul>
    </div>
  );
}

如果加載完成且沒有錯誤,則顯示客戶的列表。
使用 map 函數遍歷 customers 陣列,為每個客戶創建一個元素,顯示客戶的姓名。
使用 customer.id 作為 key 屬性,以確保每個元素都有唯一的標識。

總結

今天學到了一些前端的梅梅角角
因為時間的關係來不及補充玩
不過希望透過這篇可以學習到前端基本知識

後續的(Post,Put,Delete可以讓大家練習看看XDD) => 其實這三個才是最難的XDD

以及交互應用的場景喔~!!


上一篇
[Day23] Python專案 - 網頁開發 - (2) 高速的服務提供者Fast API
下一篇
[Day25] Python專案 - 網頁開發 - (4) Fast API 進階後端工程師該思考的幾件事
系列文
從概念到應用:Python實戰開發學習之旅31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言